/*!
 * jQuery xpathFinder v1.0.7
 * http://www.mashupeye.com/
 *
 * Copyright 2011, MashupEye
 * GPL Version 2 licenses.
 *
 * Date: Thu Sep 3 23:17:53 2011
 */
(function($) {
	$.fn.getQuery = function(options) {
		o = $.extend({
			type : 'xpath',
			highLight : false,
			fullPath : false,
			preferenceAttr : 'id',
			bgColor : 'yellow',
			border : 'yellow 1px solid',
			expansion : 3
		}, options || {});
		if (o.highLight) {
			this.highLight(o);
		}

		var path = getPath(this, '');
		selector = path.replaceAll('/', '>').replaceAll('\\[', ':eq(').replaceAll('\\]', ')')
				.replaceAll('\\:eq\\(\\@', '[').replaceAll('\'\\)', '\']');
		query = '/' + path;
		if (!o.fullPath) {
			query = '/' + query;
		}
		if (o.type == 'selector') {
			return selector;
		} else {
			return query;
		}
	}

	this.getXpath = function() {
		return query;
	}

	this.getSelector = function() {
		return selector;
	}

	$.fn.highLight = function(options) {
		op = $.extend({
			bgColor : 'yellow',
			border : 'yellow 1px solid',
			expansion : 3
		}, options || {});
		$('body').append("<div id='abs-box' class='abs'> </div>");
		$('head').append("<style>.abs{position:absolute;zoom:1;pointer-events:none;z-index:-1;}</style>");
		var div = $('#abs-box');
		if (div != this) {
			var pos = this.offset(), em = op.expansion;
			div.css({
				'left' : pos.left - em,
				'top' : pos.top - em,
				'width' : this.width() + 2 * em,
				'height' : this.height() + 2 * em
			});
			div.css({
				'background-color' : op.bgColor,
				'border' : op.border
			});
		}
	}

	function getPath(e, path) {
		var tn = e.get(0).tagName;
		if (isNullOrEmpty(e) || isNullOrEmpty(tn)) {
			return path;
		}
		var attr = getAttr(e);
		tn = tn.toLowerCase() + attr;
		path = isNullOrEmpty(path) ? tn : tn + "/" + path;
		var parentE = e.parent();
		if (isNullOrEmpty(parentE) || (!o.fullPath && attr.substring(0, 5) == '[@id=')) {
			return path;
		}
		return getPath(parentE, path);
	}

	function getAttr(e) {
		var tn = e.get(0).tagName;
		var id = e.attr('id'), clazz = e.attr('class');
		var hasId = !isNullOrEmpty(id), hasClazz = !isNullOrEmpty(clazz);
		id = "[@id='" + id + "']";
		clazz = "[@class='" + clazz + "']";
		if (hasId && hasClazz) {
			if (o.preferenceAttr.toLowerCase() == 'class') {
				return clazz;
			} else {
				return id;
			}
		} else if (hasId && !hasClazz) {
			return id;
		} else if (!hasId && hasClazz) {
			return clazz;
		} else {
			if (e.siblings(tn).size() > 0) {
				var i = e.prevAll(tn).size();
				if (o.type == 'xpath') {
					i++;
				}
				return '[' + i + ']';
			} else {
				return '';
			}
		}
	}

	function isNullOrEmpty(o) {
		return null == o || 'null' == o || '' == o || undefined == o;
	}

})(jQuery);

String.prototype.replaceAll = function(regx, t) {
	return this.replace(new RegExp(regx, 'gm'), t);
};
/*
 * A/B Tester Javascript code Author: gli
 */
;(function($) {
	//
	$.abTester = {};

	// ///////////////////////////////////////// Editor functions
	$.abTester.editor = function(options) {
		var defaults = {window: window};
		var opts = $.extend({}, defaults, options);
		var editor = this.editor;
		var thisDocument = opts.window.document;
		/**
		 * Insert a new Div for selected element
		 * 
		 * @param element
		 * @param parentElement
		 */
		editor.add = function(element, parentElement) {
		}

		/**
		 * Update the original element
		 * 
		 * @param newElement
		 *          new element string
		 * @param element
		 *          Original element
		 * @return jQuery the parent path of changed element
		 */
		editor.update = function(newElement, element) {
			var elePath = $(element).getQuery({
				type : 'selector'
			});
			var pElePath = $(element).parent().getQuery({
				type : 'selector'
			});
			var result = null;
			var does = this.getDoes();
			var undoes = this.getUndoes();
			if (elePath) {
				does.push('$("' + elePath + '").replaceWith("' + newElement.replaceAll("\'", "\\\'").replaceAll('"', '\\"')
						+ '");');
				undoes.push('$("' + elePath + '").replaceWith("' + $(element).outerHtml() + '");');
				result = $(element).replaceWith(newElement);

				$('body', thisDocument).data('ab-does', does);
				$('body', thisDocument).data('ab-undoes', undoes);
			}
			return pElePath;
		}

		editor.remove = function(element) {
			var fetched = $(element).getQuery({
				type : 'selector'
			});
			var does = this.getDoes();
			var undoes = this.getUndoes();
			if (fetched) {
				does.push('$(' + fetched + ').remove()');
				var parentFetched = $(element).parent().getQuery({
					type : 'selector'
				});
				// TODO: should check the index of children in a element
				undoes.push('$(' + parentFetched + ').append(' + $(element).outerHtml() + ')');
				$(element).remove();
			}
		}

		editor.getDoes = function() {
			return $('body', thisDocument).data('ab-does') ? $('body').data('ab-does') : new Array();
		}
		editor.getUndoes = function() {
			return $('body', thisDocument).data('ab-undoes') ? $('body').data('ab-undoes') : new Array();
		}
		return editor;
	};

	// ///////////////////////////////////////////////////////// Static
	// functions
	// outer html
	$.fn.outerHtml = function() {
		return $('<div></div>').html($(this).clone()).html();
	}
})(jQuery);

// /////////////////////////////////////////////////////////////////////////////
// /// New version for ABTester javascript library
// /// created: 20130303 22:01
// /////////////////////////////////////////////////////////////////////////////
;(function($) {
	$.fn.abTester = function(options) {
		var defaults = {
			window : window,
			filterTags : ["script", "link", "map", ".ui-dialog", "#ab-dialog", "#ab-dialog *"],
			defaultCursorClass : 'ab-cursor-default',
			overlayBar : '.ab-overlay-bar',
			overlayContainer : '.ab-overlay-container',
			blockUISettings : {
				message : null,
				blockMsgClass : 'cke_skin_kama',
				overlayCSS : {
					backgroundColor : '#fff',
					opacity : 0,
					cursor : 'default'
				}
			}
		};
		var opts = $.extend({}, defaults, options);
		if (!opts.filterTags) {
			opts.filterTags = new Array();
		}

		// init
		var selectEvents = 'mousedown.abTester mouseup.abTester keydown.abTester keypress.abTester keyup.abTester touchstart.abTester touchend.abTester touchmove.abTester';
		var $selectedElement, $overlayElement, $hoveredElement, $overlayMenu;

		if (!opts.window) {
			opts.window = this.length > 0 ? this.get(0).ownerDocument.defaultView : window;
		}
		// set blockUI in given window
		if (opts.window && opts.window.$ && opts.window.$.blockUI) {
			opts.window.$.blockUI.defaults = $.extend(opts.window.$.blockUI.defaults, opts.blockUISettings);
		}

		var $that = this.not(opts.filterTags.join(','));

		/**
		 * Enable or Disable the overlay function
		 * 
		 * @param param
		 *          enable, disable or empty
		 */
		$that.overlay = function(param) {
			if (!param || param == 'enable') {
				this.not(opts.filterTags.join(',')).each(function() {
					var $this = $(this);
					$this.bind('mouseenter.abTester', mouseEnterHandler);
					$this.bind('mouseleave.abTester', mouseLeaveHandler);
					$this.bind(selectEvents, elementSelectEventHandler);
				});
			} else if (param == 'disable') {
				this.not(opts.filterTags.join(',')).each(function() {
					$(this).unbind('.abTester');
				});
			}
		}

		/**
		 * un-overlay for the selected element
		 */
		$that.unOverlay = function() {
			var ownerDocument = this.get(0).ownerDocument;
			$(opts.overlayContainer, ownerDocument).css({
				top : 0,
				left : 0
			}).hide();
			$selectedElement = null;
			$hoveredElement = null;
			// hide menu
			$.overlayMenu.hide(ownerDocument);
			// hide blockUI
			opts.window.$.unblockUI();
			console.log("Unblock the page!");
		}

		// hover events START
		function mouseEnterHandler(event) {
			//console.log('Enter mouseEnterHandler');
			var $this = $(this);
			var ownerDocument = this.ownerDocument;
			// overlay elements
			var $overlayBars = $(opts.overlayBar, ownerDocument);

			if ($this.is('.ab-editor')) {
				return;
			}

			$this.addClass(opts.defaultCursorClass);

			if (!$selectedElement) {
				// there is no element is selected, then we can overlay this
				// element
				var offset = $this.offset();
				var width = $this.outerWidth() - 2;
				var height = $this.outerHeight() - 2;

				// add the styles for four overlay bars
				$overlayBars.eq(0).css({
					top : offset.top,
					left : offset.left,
					width : width,
					height : '2px'
				});
				$overlayBars.eq(1).css({
					top : offset.top,
					left : offset.left,
					width : '2px',
					height : height
				});
				$overlayBars.eq(2).css({
					top : offset.top + height,
					left : offset.left,
					width : width + 2,
					height : '2px',
					boxShadow : '3px 3px 8px #666'
				});
				$overlayBars.eq(3).css({
					top : offset.top,
					left : offset.left + width,
					width : '2px',
					height : height,
					boxShadow : '3px 3px 8px #666'
				});
				$overlayBars.show(); // show it

				// the element is hovered
				$hoveredElement = $this;
			}
			return false;
		}

		function mouseLeaveHandler(event) {
			//console.log('Enter mouseLeaveHandler');
			var $this = $(this);
			var ownerDocument = this.ownerDocument;

			var $overlayBars = $(opts.overlayBar, ownerDocument);

			$this.removeClass(opts.defaultCursorClass);
			// hide overlay bars
			$overlayBars.hide();
			// unset hovered element
			$hoveredElement = null;
			return false;
		}
		// hover events END

		// click events START
		function elementSelectEventHandler(event) {
			//console.log('Enter elementSelectEventHandler');
			var $this = $(this);
			var ownerDocument = this.ownerDocument;

			var $overlay = $(opts.overlayContainer, ownerDocument);
			var $overlayBars = $(opts.overlayBar, ownerDocument);

			$this.removeClass(opts.defaultCursorClass);
			$overlayBars.hide();

			if ($hoveredElement) {
				var offset = $hoveredElement.offset();
				var width = $hoveredElement.outerWidth() - 4;
				var height = $hoveredElement.outerHeight() - 4;

				$overlay.css({
					top : offset.top,
					left : offset.left,
					width : width,
					height : height
				}).show();
				$selectedElement = $hoveredElement;

				// show menus
				$overlayMenu = $selectedElement.overlayMenu({
					window: opts.window,
					of : $selectedElement,
					editor: $that
				});
				// block the background
				opts.window.$.blockUI();
				// overlay click event
				$('.blockOverlay', ownerDocument).bind('click.abTester', blockOverlayClickHandler);
				$hoveredElement = null;
				
				return false;
			}

			return true;
		}

		function blockOverlayClickHandler(event) {
			// console.log('---------------->block overlay clicked!');
			var $this = $(this);
			var ownerDocument = this.ownerDocument;
			// hide overlay container
			$(opts.overlayContainer, ownerDocument).hide();
			// unset elements
			$selectedElement = $hoveredElement = null;
			// hide blockUI
			opts.window.$.unblockUI();

			// hide menu
			if ($overlayMenu) {
				$overlayMenu.hide();
			} else {
				$.overlayMenu.hide(ownerDocument);
			}

			return false;
		}
		// click events END

		// window resize event START
		function windowResizeHandler(event) {
			// TODO: window resize event handler
		}
		// window resize event END

		// functions
		$that.getSelectedElement = function() {
			return $selectedElement;
		}

		// return current jQuery elements

		return $that.each(function(){
			
		});
	};

	// /////////////////////////////////////////////////////////////// Overlay
	// Menu Function START
	$.fn.overlayMenu = function(options) {
		var defaults = {
			window: window,
			of : null,
			editor: null
		};
		var opts = $.extend({}, defaults, options);

		var ownerDocument = this.get(0).ownerDocument;
		var $menuContainer = $('#ab-menus', ownerDocument);
		var $menus = $(".menus", $menuContainer);

		// clear the menus
		$menus.empty();

		var nodeName = $(this).get(0).nodeName;
		var jsonMenuBar = {
			'class' : 'ab-menu-bar',
			'isMenuBar' : true
		};
		var sub_menu_edit_html = {
			'class' : 'edit-html',
			'title' : 'Edit HTML',
			'action' : function(event) {
				$menuContainer.hide();
				opts.window.$.unblockUI();
				opts.window.$.abDialog({
					window: opts.window,
					element: opts.of,
					event: event,
					view: 'edit-html',
					editor: opts.editor
				})
			}
		};
		var sub_menu_edit_text = {
			'class' : 'edit-text',
			'title' : 'Edit Text',
			'action' : function() {
			}
		};
		var sub_menu_change_image = {
			'class' : 'change-image',
			'title' : 'Change Image',
			'action' : function() {
			}
		};
		var sub_menu_make_hyperlink = {
			'class' : 'make-link',
			'title' : 'Make Hyperlink',
			'action' : function() {
			}
		};
		var sub_menu_edit_hyperlink = {
			'class' : 'edit-link',
			'title' : 'Edit Hyperlink',
			'action' : function() {
			}
		};
		var sub_menu_edit_style = {
			'class' : 'edit-style',
			'title' : 'Edit Style',
			'action' : function() {
			}
		};

		var jsonMenus = [ {
			'class' : 'edit',
			'title' : 'Edit Element',
			'hasSubMenu' : true,
			'subMenus' : [ {
				'class' : 'edit-text',
				'title' : "Edit Text",
				'action' : function() {
				}
			}, {
				'class' : 'edit-html',
				'title' : 'Edit HTML',
				'action' : function() {
				}
			} ]
		}, {
			'class' : 'insert',
			'title' : 'Insert HTML',
			'action' : function() {
				console.log('Insert HTML menu clicked!');
			}
		}, jsonMenuBar, {
			'class' : 'remove',
			'title' : 'Remove',
			'action' : function() {
				console.log('Remove menu clicked!');
			}
		} ];

		// TODO: change the menu json when tag is different
		switch (nodeName.toUpperCase()) {
		case 'IMG':
			jsonMenus[0].subMenus = [ sub_menu_edit_html, jsonMenuBar, sub_menu_change_image, jsonMenuBar,
					sub_menu_edit_hyperlink, sub_menu_edit_style ];
			break;
		case 'A':
			jsonMenus[0].subMenus = [ sub_menu_edit_html, jsonMenuBar, sub_menu_edit_hyperlink, sub_menu_edit_style ];
			break;
		case 'P':
			jsonMenus[0].subMenus = [ sub_menu_edit_html, jsonMenuBar, sub_menu_make_hyperlink, sub_menu_edit_style ];
			break;
		case 'DIV':
		case 'OBJECT':
			jsonMenus[0].subMenus = [ sub_menu_edit_html, sub_menu_edit_text, jsonMenuBar, sub_menu_edit_style ];
			break;
		case 'INPUT':
			jsonMenus[0].subMenus = [ sub_menu_edit_html, sub_menu_edit_text, jsonMenuBar, sub_menu_change_image,
					jsonMenuBar, sub_menu_make_hyperlink, sub_menu_edit_style ];
		case 'SPAN':
			jsonMenus[0].subMenus = [ sub_menu_edit_html, sub_menu_edit_text, jsonMenuBar, sub_menu_change_image,
					jsonMenuBar, sub_menu_edit_style ];
			break;
		default:
		}

		$(".title", $menuContainer).html(nodeName.toUpperCase());

		function defaultAction(event, view) {
			$menuContainer.hide();
			opts.window.$.unblockUI();
			opts.window.$.abDialog({
				window: opts.window,
				element: opts.of,
				event: event,
				view: view,
				editor: opts.editor
			})
		}

		$(jsonMenus).each(function() {
			if (this.isMenuBar) {
				var $hr = $("<hr>");
				$hr.addClass(this.class);
				$menus.append($hr);
				if (this.action)
					$span.bind('click', this.action);
			} else {
				var $span = $("<span></span>");
				$span.addClass(this.class).html(this.title);
				$menus.append($span);

				if (this.hasSubMenu) {
					$span.addClass('submenu');
					var submenuStr = "<div class='subMenus'><div class='padding'>";
					$(this.subMenus).each(function() {
						var submenuItemStr = "";
						if (this.isMenuBar) {
							submenuItemStr = "<hr class='" + this.class + "'>";
						} else {
							submenuItemStr = "<span class='" + this.class + "'>" + this.title + "</span>";
						}
						submenuStr += submenuItemStr;
					});
					submenuStr += "</div></div>";
					$span.append(submenuStr);
					// bind sub menu action
					$(this.subMenus).each(function(i, j) {
						var $thisAction = this.action;
						if ($thisAction) {
							$('.padding', $span).children().eq(i).bind('click', function(event) {
								//$thisAction(event);
								defaultAction(event, $(this).attr("class"))
								// hide menu
								$.overlayMenu.hide(opts);
							});
						}
					});
					$span.hover(function() {
						var ownerDoc = this.ownerDocument;
						// check the position of parent
						var spanOffset = $(this).offset();
						var spanWidth = $(this).outerWidth();
						var spanHeight = $(this).outerHeight();
						if (spanOffset.left + spanWidth * 2 > $(ownerDoc.body).outerWidth()) {
							$('.subMenus', $span).css({left: '-149px'}).show();
						} else {
							$('.subMenus', $span).show();
						}
					}, function() {
						$('.subMenus', $span).hide();
					});
				} else {
					var $thisAction = this.action;
					if ($thisAction) {
						$span.bind('click', function() {
							// hide menu
							$thisAction();
							$.abMenu.hide(opts);
						});
					}
				}
			}
		});

		if (opts.of) {
			var offset = $(opts.of).offset();
			var width = $(opts.of).outerWidth();
			var height = $(opts.of).outerHeight();
			var menuTop, menuLeft;
			if (window.screen.availWidth > offset.left + width + 152) {
				menuLeft = offset.left + width + 10;
				if (window.innerHeight + window.scrollY > offset.top + 152) {
					menuTop = offset.top;
				} else {
					menuTop = offset.top - height;
				}
			} else {
				menuLeft = offset.left + width - 152;
				if (window.innerHeight + window.scrollY > offset.top + 152) {
					menuTop = offset.top;
				} else {
					menuTop = offset.top - height;
				}
			}
			$menuContainer.css({
				top : menuTop,
				left : menuLeft
			}).show();
		} else {
			$menuContainer.css({
				top : opts.top,
				left : opts.left
			}).show();
		}

		// hide event, hide current menu
		this.hide = function() {
			$menuContainer.hide();
		}
		return this;
	};

	$.overlayMenu = {
		hide : function(curDoc) {
			$("#ab-menus", curDoc).hide();
		}
	}
	// /////////////////////////////////////////////////////////////// Overlay
	// Menu Function END

	// ///////////////////////////////////////// Dialog
	$._abDialog = function(options) {
		var defaults = {
			currentWindow : null,
			element : null
		};
		var opts = $.extend({}, defaults, options);
		$("#ab-dialog", opts.currentWindow.document).dialog({
			autoOpen : true,
			height : 300,
			width : 500,
			modal : true,
			resizable : false,
			open : function(event, ui) {
				//$('#html-editor').val($(opts.element).outerHtml());
				$('.ui-dialog, .ui-dialog *, .ui-widget-overlay').bind('click', function(event) {
					//event.preventDefault();
					//event.stopPropagation();
					//return false;
				});
			},
			buttons : {
				"OK" : function(event) {
					// TODO: check if changed
					var changed = true;
					if (changed) {
						// save the change
						var editor = $.abTester.editor();
						var result = editor.update($('#html-editor').val(), $selectedElement);
						$(result, opts.currentWindow.document).children().overlay();
					}
					//
					$(this).dialog('close');
					// remove selected
					$.unOverlay(opts);
				},
				"Cancel" : function(event) {
					event.stopPropagation();
					$(this).dialog('close');

					// remove selected
					$.unOverlay(opts);
				}
			},
			close : function(event) {
				// close the dialog
				event.stopPropagation();

				// remove selected
				$.unOverlay(opts);
			}
		});
	}
})(jQuery);
